#pragma once
#include <iostream>
#include <sys/poll.h>
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Socket.hpp"

using namespace LogModule;

class PollServer{

	const static int size = sizeof(fd_set) * 8;
	const static int defaultfd = -1;

public:

	PollServer(uint16_t port){
		_listensock = std::make_unique<TcpSocket>();
		_listensock->BulidTcpSocketMethod(port);
		
		_isrunning = false;
		for(int i = 0; i < size; i++){
			_pollfd[i].fd = defaultfd;
			_pollfd[i].events = 0;
			_pollfd[i].revents = 0;
		}
		_pollfd[0].fd = _listensock->GetFd();
		_pollfd[0].events = POLLIN; // 设置为只关注读事件
	}

	void Start(){
		_isrunning = true;
		while(_isrunning){
			int maxsize = 0;
			for(int i = 0; i < size; i++){
				if(_pollfd[i].fd != defaultfd)
					maxsize++;
			}
			Printfd();

			struct pollfd* fds = _pollfd;
			int ret = poll(fds, maxsize, -1);
			switch(ret){
				case -1:
					LOG(LogLevel::ERROR) << "poll error";
					break;
				case 0:
					LOG(LogLevel::WARNING) << "poll timeout";
					break;
				default:
					Dispatch();
					break;
			}
		}

	}

	void Dispatch(){ 
		for(int i = 0; i < size; i++){
			if(_pollfd[i].fd == defaultfd)
				continue;
			
				if(_pollfd[i].revents & POLLIN){
					if(_pollfd[i].fd == _listensock->GetFd()){
						// 监听套接字
						Accepter();
					}
					else{
						// 数据套接字
						Receiver(_pollfd[i].fd);
					}	
				}
		}
	}

	void Accepter(){
		InetAddr client;
		int fd = _listensock->Accept(&client);
		if(fd < 0){
			LOG(LogLevel::ERROR) << "accept error";
			return;
		}

		// 将新的套接字加入数组
		int pos = 0;
		for(int i = 1; i < size; i++){
			if(_pollfd[i].fd == defaultfd){
				pos = i;
				break;
			}
		}

		// 插入新的套接字
		if(pos != 0){
			_pollfd[pos].fd = fd;
			_pollfd[pos].events = POLLIN;
			_pollfd[pos].revents = 0;
		}
		else{
			LOG(LogLevel::ERROR) << "_fd_array is full";
			close(fd);
		}
	}

	void Receiver(int fd){
		char buffer[1024];
		int ret = recv(fd, buffer, sizeof(buffer)-1, 0);
		if(ret > 0){
			buffer[ret] = 0;
			std::cout<<buffer<<std::endl;
		}
		else if(ret == 0){
			// 对端关闭
			LOG(LogLevel::INFO) << "client close";
			close(fd);
			// 清除文件描述符
			for(int i = 0; i < size; i++){
				if(_pollfd[i].fd == fd){
					_pollfd[i].fd = defaultfd;
					break;
				}
			}
		}
		else{
			LOG(LogLevel::ERROR) << "recv error";
			close(fd);
			for(int i = 0; i < size; i++){
				if(_pollfd[i].fd == fd){
					_pollfd[i].fd = defaultfd;
					break;
				}
			}
		}
	}

	void Stop(){
		_isrunning = false;
	}

	void Printfd(){
		std::cout<<"_fd_array: ";
		for(int i = 0; i < size; i++){
			if(_pollfd[i].fd != defaultfd)
				std::cout<<_pollfd[i].fd<<" ";
		}
		std::cout<<std::endl;
	}
	~PollServer(){}


private:
	std::unique_ptr<Socket> _listensock;
	bool _isrunning;
	struct pollfd _pollfd[size];
};